const userModel = require("../models/usersModel")
// jwt--token操作
const jwt = require('jsonwebtoken');
// redis数据库操作
const Redis = require('ioredis');
const redis = new Redis(); // 默认连接到 localhost:6379
// 网络请求
const axios = require('axios');
// 引入dayjs
const dayjs = require('dayjs');

// 微信配置
// AppID(小程序ID):  wx700465c558dcf1c2
// AppSecret(小程序密钥):372737e1d5387f5e9959fa4f3c869d0a
const WX_CONFIG = {
    appId: 'wx700465c558dcf1c2',
    appSecret: '372737e1d5387f5e9959fa4f3c869d0a',
    loginUrl: 'https://api.weixin.qq.com/sns/jscode2session'
};
// 0.小程序段的登录/注册
exports.mpLogin = async (req, res) => {
    try {
        // 1. 获取微信登录凭证
        const { code, phone } = req.body;
        // const { code, userInfo } = req.body;
        if (!code) return res.status(400).json({ code: 400, message: '缺少必要参数' });
        // 2. 获取 openid 和 session_key
        const wxResult = await axios.get(WX_CONFIG.loginUrl, {
            params: {
                appid: WX_CONFIG.appId,
                secret: WX_CONFIG.appSecret,
                js_code: code,
                grant_type: 'authorization_code'
            }
        });
        const { openid, session_key } = wxResult.data;
        if (!openid) return res.status(400).json({ code: 400, message: `微信登录失败: ${wxResult.data.errmsg}` });
        // res.status(200).json({ code: 0, message: '微信登录成功', openid })
        // 到此为止，想要的openid已经拿到
        // 3. 先检查数据库中此openid是否已经存在用户---存在则登录，不存在则注册
        const existingUser = await userModel.existingUser(openid)
        console.log("用户是否登录：",existingUser)
        //   “||” 两个有一个为true时就走if
        if (!existingUser || existingUser.length === 0) {
            // 4. 这里表示账号未注册，执行注册的方法
            const register = await userModel.register(phone, openid)
            if (!register) {
                return res.status(500).json({ // 修改为500错误
                    code: 500,
                    message: '用户注册失败'
                });
            } else {
                // 再根据openid去找这个注册账号的记录
                const existingUser_now = await userModel.existingUser(openid)
                res.json({ code: 0, message: '已成功注册，登录成功', result: existingUser_now })
            }
        } else {
            // 5. 这里表示账号已经注册过了，就直接登录成功
            res.json({ code: 0, message: '此账号已注册，登录成功', result: existingUser })
        }
    } catch (error) {
        console.log(error)
        res.json({ code: -1, msg: error })
    }
}

// 1.用户的登录--手机号登录--pc段
exports.login = async (req, res) => {
    let { phone } = req.body

    // 验证是否携带参数
    if (!phone) {
        res.json({
            code: -2,
            msg: "请求参数不合法"
        })
    }

    const new_phone = phone.trim();
    // 验证手机号格式
    if (!/^1[3-9]\d{9}$/.test(new_phone)) {
        res.status(400).json({
            code: 400,
            msg: "手机号格式不正确"
        });
    }
    try {
        // 进行查询数据库内容
        const results = await userModel.login(new_phone)
        if (results.length === 0) {
            res.json({ code: -2, msg: '账号不存在' });
        } else {
            const token = jwt.sign(
                {
                    id: results[0].id,
                    username: results[0].username
                },
                '39qw89r23890', // 自定义密钥
                {
                    expiresIn: '24h' // 过期时间
                }
            );

            console.log('当前登录用户的token', token);
            // 切记：这里名字能带空格会出错的
            let key = `uid:${results[0].id}`
            redis.setex(key, 86400, token, (error, reslut) => {
                if (error) {
                    console.log(error)
                    return res.status(500).json({ code: 500, msg: "操作redis时出错了" });
                }
                res.json({ code: 0, msg: "登录成功！", data: { userInfo: { ...results[0] }, token } });
            })
            // res.json({ code: 0, msg: '登录成功！', data: results })
        }
    } catch (error) {
        console.log(error)
        res.json({ code: -1, msg: error })
    }
}

// 2.退出登录--清除token
exports.logout = (req, res) => {
    // 从请求头中获取Authorization字段，并提取token
    const authHeader = req.headers.authorization;
    const token = authHeader ? authHeader.split(' ')[1] : null; // 提取token
    console.log('未处理：', authHeader, '处理的：', token)
    if (!token) {
        return res.status(401).json({ code: 401, msg: "请提供token" });
    }
    const decoded = jwt.verify(token, '39qw89r23890');
    const { id } = decoded;
    let key = `uid:${id}`
    // 操作redis数据库---删除退出用户的token
    redis.del(key, (error, result) => {
        if (error) {
            console.log(error)
            return res.status(500).json({ code: 500, msg: "操作redis时出错了" });
        }
        res.json({ code: 0, msg: "退出登录成功！" });
    })
}

// 3.用户的列表
exports.usersList = (req, res) => {
    let { page, pageSize, username, realname, phone } = req.query
    if (!page && !pageSize) {
        res.status(400).json({
            code: 400,
            msg: "缺少必要的参数"
        })
    }
    const results = userModel.userlist(Number(page), Number(pageSize), username, realname, phone)
    results.then((results) => {
        console.log(results)
        res.json({ code: 0, msg: "用户列表请求成功！", results })
    }).catch((error) => {
        console.log(error)
        res.json({ code: -1, msg: "用户列表请求失败！", error })
    })
}

// 4.用户列表的删除---更改状态
exports.Fdelte = async (req, res) => {
    let { id } = req.body
    try {
        // 获取当前时间
        const now = dayjs();
        console.log(now.format('YYYY-MM-DD HH:mm:ss')); // 2023-08-15 14:30:45
        const now_dateTime = now.format('YYYY-MM-DD HH:mm:ss')
        const results = await userModel.Fdelte(Number(id), now_dateTime)
        console.log(results)
        res.json({ code: 0, msg: "用户删除成功！", results })
    } catch (error) {
        console.log(error)
        res.json({ code: -1, msg: "用户删除失败！", error })
    }
}

// 5.用户列表的删除---删除数据
exports.Tdelte = async (req, res) => {
    let { id } = req.body
    try {
        const results = await userModel.Tdelte(Number(id))
        console.log(results)
        res.json({ code: 0, msg: "用户删除成功！", results })
    } catch (error) {
        console.log(error)
        res.json({ code: -1, msg: "用户删除失败！", error })
    }
}

// 6.用户列表的查看数据--获取记录
exports.get = async (req, res) => {
    let { id } = req.query
    try {
        const results = await userModel.get(Number(id))
        if (!results.length) {
            res.json({ code: 0, msg: "当前用户数据可能已被删除！", results })
        }
        console.log(results)
        res.json({ code: 0, msg: "当前用户数据请求成功成功！", results })
    } catch (error) {
        console.log(error)
        res.json({ code: -1, msg: "当前用户数据请求成功失败！", error })
    }
}

// 7.用户列表的修改记录
exports.set = async (req, res) => {
    let { id, username, address, age, gender, realname, hobby, phone,userUrl,role } = req.body
    try {
        // 获取当前时间
        const now = dayjs();
        console.log(now.format('YYYY-MM-DD HH:mm:ss')); // 2023-08-15 14:30:45
        const now_dateTime = now.format('YYYY-MM-DD HH:mm:ss')
        const results = await userModel.set(Number(id), username, address, age, gender, realname, hobby, phone, now_dateTime,userUrl,role)
        // 判断更新结果
        if (!results || results.affectedRows === 0) { // 根据ORM具体返回值判断
            return res.status(400).json({
                code: 400,
                msg: "更新失败：用户不存在或数据未变化",
            });
        }
        console.log(results)
        res.json({ code: 0, msg: "当前用户数据请求成功成功！", results })
    } catch (error) {
        console.log(error)
        res.json({ code: -1, msg: "当前用户数据请求成功失败！", error })
    }
}


// 文件上传
exports.uploads = async (req, res) => {
    // 获取请求头中的token
    const token = req.headers.authorization;

    // 检查token是否存在
    if (!token) {
        return res.status(400).json({ code: 1, msg: "无token，请先登录" });
    }

    // 获取上传的文件信息
    console.log("aaaa", req.files)
    let { id } = req.body
    let one_f = req.files.file;
    if(!one_f){
        return res.status(400).json({ code: 1, msg: "请求参数不符合要求" });

    }

    var originalFilename = one_f.originalFilename;

    var file_path = one_f.path;

    try {
        // 读取文件内容并保存到新位置
        if (file_path) {
            let date = new Date();
            let new_name = date.getTime() + path.extname(originalFilename);

            // 生成网络可访问的URL
            const baseUrl = 'http://localhost:3000'; // 你的服务器地址
            const fileUrl = `${baseUrl}/uploads/${new_name}`;

            let new_file_name = 'public/uploads/' + new_name;
            console.log("图片路径：：：：：：：：", new_file_name, fileUrl)
            // 把图片处理好的路径new_file_name存到名为user的数据库的picture的字段里
            const image = await assigModel.uploads(new_file_name, Number(id), file_path);

            // console.log(image)
            // res.json({ code: 0, msg: "图片上传成功！", image })
            fs.rename(file_path, new_file_name, (err) => {
                if (err) {
                    console.log(err)
                    res.json({ status: -1, msg: err.message });
                } else {
                    res.json({
                        msg: "文件上传完成", code: 0, data: {
                            fileName: new_file_name,
                            ext: path.extname(new_file_name)
                        },
                        image
                    })
                }
            });
        } else {
            res.json({
                status: -2,
                msg: "图片未找到"
            })
        }
    } catch (error) {
        console.log('Error uploading image:', error);
        res.json({ code: 1, msg: error.message });
    }
}

// 文件删除
exports.deleteImage = async (req, res) => {
    // 鉴权验证
    const token = req.headers.authorization;
    if (!token) {
        return res.status(401).json({ code: 1, msg: "无token，请先登录" });
    }
    // public/uploads/1742372086892.jpg
    try {
        // 参数校验
        const { id, filePath } = req.body;
        const delete_url = `../${filePath}`
        if (!filePath) {
            return res.status(400).json({
                code: 2,
                msg: "缺少必要参数: filePath"
            });
        }

        // 安全路径校验
        // const safePath = path.normalize(filePath).replace(/^(\.\.[\/\\])+/g, '');
        // const fullPath = path.join(__dirname, '../public/uploads', safePath);

        if (!fullPath.startsWith(path.join(__dirname, '../public/uploads'))) {
            return res.status(403).json({
                code: 3,
                msg: "非法文件路径"
            });
        }

        // 数据库记录删除
        const deleteResult = await assigModel.deleteByPath(Number(id));
        // 证明存在此数据--此作业
        if (!deleteResult.changedRows) {
            return res.status(404).json({
                code: 4,
                msg: "数据库记录不存在"
            });
        }

        // 物理文件删除
        // fs.unlinkSync(delete_url);
        await fs.promises.access(delete_url, fs.constants.F_OK); // 异步操作，不会阻塞代码
        await fs.promises.unlink(delete_url);

        res.json({
            code: 0,
            msg: "文件删除成功",
            data: {
                deletedPath: safePath,
                timestamp: new Date().toISOString()
            }
        });

    } catch (error) {
        // 错误分类处理
        if (error.code === 'ENOENT') {
            return res.status(404).json({
                code: 5,
                msg: "文件不存在"
            });
        }

        console.error('删除操作失败:', error);
        res.status(500).json({
            code: 9,
            msg: "服务器内部错误",
            detail: error.message
        });
    }
};



// 7.统计图数据接口---活动热度表---统计每个活动的热度
exports.hotChart = async (req,res) => {
    try{
        const results = await userModel.hotChart()
         // 判断更新结果
         if (!results || results.affectedRows === 0) { // 根据ORM具体返回值判断
            return res.status(400).json({
                code: 400,
                msg: "请求失败：数据库获取失败",
            });
        }
        console.log(results)
        res.json({ code: 0, msg: "活动热度表数据请求成功成功！", results })
    }catch(error){
        console.log(error)
        res.json({ code: -1, msg: "活动热度表数据请求成功失败！", error })
    }
}

// 8.统计图数据接口---用户活动表---统计每个用户报名的次数
exports.userSign = async (req,res) => {
    try{
        const results = await userModel.userSign()
         // 判断更新结果
         if (!results || results.affectedRows === 0) { // 根据ORM具体返回值判断
            return res.status(400).json({
                code: 400,
                msg: "请求失败：数据库获取失败",
            });
        }
        console.log(results)
        res.json({ code: 0, msg: "用户活动表数据请求成功成功！", results })
    }catch(error){
        console.log(error)
        res.json({ code: -1, msg: "用户活动表数据请求成功失败！", error })
    }
}

// 9.统计图数据接口---用户贡献表---统计每个用户发布活动的占比
exports.userPublish = async (req,res) => {
    try{
        const results = await userModel.userPublish()
         // 判断更新结果
         if (!results || results.affectedRows === 0) { // 根据ORM具体返回值判断
            return res.status(400).json({
                code: 400,
                msg: "请求失败：数据库获取失败",
            });
        }
        console.log(results)
        res.json({ code: 0, msg: "用户贡献表数据请求成功成功！", results })
    }catch(error){
        console.log(error)
        res.json({ code: -1, msg: "用户贡献表数据请求成功失败！", error })
    }
}